package com.gemalto.Kryptik.Gui;

import javax.swing.JTextArea;
import javax.swing.text.*;
import javax.swing.undo.*;
import javax.swing.border.LineBorder;
import javax.swing.event.*;
import com.gemalto.Kryptik.Gui.*;
import com.gemalto.Kryptik.*;
import java.awt.event.*;
import java.awt.*;
import gnu.regexp.*;

public class SearchableTextArea extends SearchableTextAreaInterface implements CaretListener,KeyListener, FocusListener {

	private FindDialog fd;
	private static String lastTextToSearch;
	private Counter c;

    	/**
     	* Listener for the edits on the current document.
     	*/
    	protected UndoableEditListener undoHandler = new UndoHandler();

    	/** UndoManager that we add edits to. */
    	protected UndoManager undo = new UndoManager();

	class UndoHandler implements UndoableEditListener {

		/**
		 * Messaged when the Document has created an edit, the edit is
		 * added to <code>undo</code>, an instance of UndoManager.
		 */
		public void undoableEditHappened(UndoableEditEvent e) {
		    undo.addEdit(e.getEdit());
		//    undoAction.update();
		//    redoAction.update();
		}
	}



	public SearchableTextArea(Counter c){
		setLineWrap(true);
		//setBorder(new LineBorder(java.awt.Color.black));
		//setBorder(new javax.swing.border.TitledBorder("Algo"));
		setRows(5);
		setFont(new java.awt.Font ("Courier New", 0, 12));
		setDocument(new HexDocument(0));
		addKeyListener(this);
		addFocusListener(this);
		addCaretListener(this);
		this.c=c;
		fd=new FindDialog(this, true);
		getDocument().addUndoableEditListener(undoHandler);
	}
	

	public void setDocument(Document doc){
		super.setDocument(doc);
		doc.addUndoableEditListener(undoHandler);
	}

	/* TAB should transfer focus to next component, which is
         * not normal behaviour for TextComponent. Easy solution is
 	 * to redefine following method.
	 */
    public boolean isManagingFocus() { return false; } 


	/* Update counter, when user focused this text area */
	public void focusGained(FocusEvent evt){
		if (c!=null) c.update(this);
	}

	
	public void focusLost(FocusEvent evt){
	}

	
	public void keyTyped(KeyEvent evt){
	}
	

	public void keyReleased(KeyEvent evt){
		if (c!=null)  c.update((JTextComponent)this);
	}
	

	public void keyPressed(KeyEvent evt){
       if ( evt.getKeyCode()==KeyEvent.VK_F && evt.getModifiers()==KeyEvent.CTRL_MASK){
        	// Setup dialog position
        	Point myCorner = getLocationOnScreen();
        	Dimension mySize = getSize();
        	Dimension dialogSize = fd.getSize();
        	myCorner.translate(mySize.width/2 - dialogSize.width/2, mySize.height/2 - dialogSize.height/2);
        	fd.setLocation(myCorner);
        	fd.setVisible(true);
      	} else if ( evt.getKeyCode()==KeyEvent.VK_G && evt.getModifiers()==KeyEvent.CTRL_MASK){
         	findNext();
      	} else if ( evt.getKeyCode()==KeyEvent.VK_Z && evt.getModifiers()==KeyEvent.CTRL_MASK){
         	if ( undo.canUndo()) undo.undo();
      	} else if ( evt.getKeyCode()==KeyEvent.VK_R && evt.getModifiers()==KeyEvent.CTRL_MASK){
         	if ( undo.canRedo()) undo.redo();
      	}


  	}


	public void caretUpdate(CaretEvent e){
		if (c!=null) c.update((JTextComponent)this);
	}

	public void find(String text){
    	this.lastTextToSearch = text;
    	String t = getText();
 
    	try {
        	RE rexp = new RE(text);
        	REMatch match = rexp.getMatch(t, getCaretPosition());
        	if ( match!=null)
            	select(match.getStartIndex(),match.getEndIndex());
        	else Messenger.warning("No match found.");
    	} catch  (REException e) { Messenger.error(e.getMessage());}
	}


	public void findNext(){
    	find(this.lastTextToSearch);
	}


}
